﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.Library.Helper
{
    /// <summary>
    /// 日期/时间助手类
    /// </summary>
    public static class DateTimeHelper
    {
        #region 使用提示
        //DateTime dateTimeNow = DateTime.Now;
        ////本月第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////本月最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////上月第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfPrevMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////上月最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfPrevMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////下月第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfNextMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////下月最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfNextMonth(dateTimeNow).ToString("yyyy/MM/dd");

        ////前三个月第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfAssignMonth(dateTimeNow, -3).ToString("yyyy/MM/dd");

        ////前三个月最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfAssignMonth(dateTimeNow, -3).ToString("yyyy/MM/dd");

        ////后三个月第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfAssignMonth(dateTimeNow, 3).ToString("yyyy/MM/dd");

        ////后三个月的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfAssignMonth(dateTimeNow, 3).ToString("yyyy/MM/dd");

        ////去年当月的第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfAssignMonthAndYear(dateTimeNow, 0, -1).ToString("yyyy/MM/dd");

        ////去年当月的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfAssignMonthAndYear(dateTimeNow, 0, -1).ToString("yyyy/MM/dd");

        ////当年的第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////当年的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////去年的第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfPrevYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////去年的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfPrevYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////明年的第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfNextYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////明年的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfNextYear(dateTimeNow).ToString("yyyy/MM/dd");

        ////指定N年前的第一天
        //txtDateHelperTest.Text = DateTimeHelper.FirstDayOfAssignYear(dateTimeNow,-2).ToString("yyyy/MM/dd");

        ////指定N年前的最后一天
        //txtDateHelperTest.Text = DateTimeHelper.LastDayOfAssignYear(dateTimeNow, -2).ToString("yyyy/MM/dd");
        #endregion

        /// <summary>
        /// 获取指定时间的第一天
        /// </summary>
        /// <param name="dateTime">要取得月份第一天的时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfMonth(DateTime dateTime)
        {
            return FirstDayOfAssignMonth(dateTime, 0);
        }

        //// <summary>
        /// 获取指定时间的最后一天
        /// </summary>
        /// <param name="dateTime">要取得月份最后一天的时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfMonth(DateTime dateTime)
        {
            return LastDayOfAssignMonth(dateTime, 0);
        }

        //// <summary>
        /// 取得上个月第一天
        /// </summary>
        /// <param name="dateTime">要取得上个月第一天的当前时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfPrevMonth(DateTime dateTime)
        {
            return FirstDayOfAssignMonth(dateTime, -1);
        }

        //// <summary>
        /// 取得上个月的最后一天
        /// </summary>
        /// <param name="dateTime">要取得上个月最后一天的当前时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfPrevMonth(DateTime dateTime)
        {
            return LastDayOfAssignMonth(dateTime, -1);
        }

        //// <summary>
        /// 取得下个月第一天
        /// </summary>
        /// <param name="dateTime">要取得上个月第一天的当前时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfNextMonth(DateTime dateTime)
        {
            return FirstDayOfAssignMonth(dateTime, 1);
        }

        //// <summary>
        /// 取得下个月的最后一天
        /// </summary>
        /// <param name="dateTime">要取得上个月最后一天的当前时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfNextMonth(DateTime dateTime)
        {
            return LastDayOfAssignMonth(dateTime, 1);
        }

        /// <summary>
        /// 获取指定时间指定月份前/后的第一天
        /// </summary>
        /// <param name="dateTime">指定的时间</param>
        /// <param name="iAssignMonthAmount">指定的月份 0为当前月份;负数为前N月;正数为后N月</param>
        /// <returns></returns>
        public static DateTime FirstDayOfAssignMonth(DateTime dateTime, int iAssignMonthAmount)
        {
            return FirstDayOfAssignMonthAndYear(dateTime, iAssignMonthAmount, 0);
        }

        /// <summary>
        /// 获取指定时间指定月份前/后的最后一天
        /// </summary>
        /// <param name="dateTime"></param>
        /// <param name="iAssignMonthAmount"></param>
        /// <returns></returns>
        public static DateTime LastDayOfAssignMonth(DateTime dateTime, int iAssignMonthAmount)
        {
            return LastDayOfAssignMonthAndYear(dateTime, iAssignMonthAmount, 0);
        }

        /// <summary>
        /// 获取指定日期当年的第一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfYear(DateTime dateTime)
        {
            return FirstDayOfAssignYear(dateTime, 0);
        }

        /// <summary>
        /// 获取指定日期当年的最后一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfYear(DateTime dateTime)
        {
            return LastDayOfAssignYear(dateTime, 0);
        }

        /// <summary>
        /// 获取指定日期去年的第一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfPrevYear(DateTime dateTime)
        {
            return FirstDayOfAssignYear(dateTime, -1);
        }

        /// <summary>
        /// 获取指定日期去年的最后一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfPrevYear(DateTime dateTime)
        {
            return LastDayOfAssignYear(dateTime, -1);
        }

        /// <summary>
        /// 获取指定日期明年的第一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime FirstDayOfNextYear(DateTime dateTime)
        {
            return FirstDayOfAssignYear(dateTime, 1);
        }

        /// <summary>
        /// 获取指定日期明年的最后一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <returns></returns>
        public static DateTime LastDayOfNextYear(DateTime dateTime)
        {
            return LastDayOfAssignYear(dateTime, 1);
        }

        /// <summary>
        /// 获取指定日期 指定年份 前/后 的第一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <param name="iAssignYearAmount">指定的年份 0为当前年份;负数为前N年;正数为后N年</param>
        /// <returns></returns>
        public static DateTime FirstDayOfAssignYear(DateTime dateTime, int iAssignYearAmount)
        {
            return FirstDayOfAssignMonthAndYear(dateTime, 1 - dateTime.Month, iAssignYearAmount);
        }

        /// <summary>
        /// 获取指定日期 指定年份 前/后 的最后一天
        /// </summary>
        /// <param name="dateTime">指定时间</param>
        /// <param name="iAssignYearAmount">指定的年份 0为当前年份;负数为前N年;正数为后N年</param>
        /// <returns></returns>
        public static DateTime LastDayOfAssignYear(DateTime dateTime, int iAssignYearAmount)
        {
            return LastDayOfAssignMonthAndYear(dateTime, 12 - dateTime.Month, iAssignYearAmount);
        }

        /// <summary>
        /// 获取指定时间指定 年份 前/后 和 月份前/后的第一天
        /// </summary>
        /// <param name="dateTime">指定的时间</param>
        /// <param name="iAssignMonthAmount">指定的月份 0为当前月份;负数为前N月;正数为后N月</param>
        /// <param name="iAssignYearAmount">指定的年份 0为当前年份;负数为前N年;正数为后N年</param>
        /// <returns></returns>
        public static DateTime FirstDayOfAssignMonthAndYear(DateTime dateTime, int iAssignMonthAmount, int iAssignYearAmount)
        {
            return dateTime.AddDays(1 - dateTime.Day).AddMonths(iAssignMonthAmount).AddYears(iAssignYearAmount);
        }

        /// <summary>
        /// 获取指定时间指定 年份 前/后 和 月份前/后的最后一天
        /// </summary>
        /// <param name="dateTime"></param>
        /// <param name="iAssignMonthAmount"></param>
        /// <returns></returns>
        public static DateTime LastDayOfAssignMonthAndYear(DateTime dateTime, int iAssignMonthAmount, int iAssignYearAmount)
        {
            return dateTime.AddDays(1 - dateTime.Day).AddMonths(1 + iAssignMonthAmount).AddDays(-1).AddYears(iAssignYearAmount);
        }

        /// <summary>
        /// 转换时间为unix时间戳
        /// </summary>
        /// <param name="date">需要传递UTC时间,避免时区误差,例:DataTime.UTCNow</param>
        /// <returns></returns>
        public static long ConvertToUnixTime(DateTime date)
        {
            //DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            //TimeSpan diff = date - origin;
            //return Math.Floor(diff.TotalSeconds);
            return (date.ToUniversalTime().Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000;
        }

        /// <summary>
        /// Unix时间戳转换为日期类型
        /// </summary>
        /// <param name="timeStamp">时间戳</param>
        /// <returns></returns>
        public static DateTime UnixTimeToDateTime(string timeStamp)
        {
            //DateTime dateTimeStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            //long lTime = long.Parse(timeStamp + "0000000");
            //TimeSpan toNow = new TimeSpan(lTime);
            //return dateTimeStart.Add(toNow);
            DateTime dateTime = DateTime.MinValue;
            long lTimeStamp = 0;
            try
            {
                lTimeStamp = Convert.ToInt64(timeStamp);
                dateTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(lTimeStamp);
            }
            catch
            {

            }
            return dateTime;
        }
    }
}
